package com.campusbook.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import com.campusbook.util.LoggingBeanPostProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * Spring配置类，演示核心特性：
 * 1. Bean生命周期回调
 * 2. BeanFactoryPostProcessor
 * 3. Environment抽象
 * 4. Resources
 * 5. 验证器配置
 */
@Configuration
@ComponentScan(basePackages = "com.campusbook")
@PropertySource("classpath:application.properties")
public class AppConfig implements BeanFactoryPostProcessor {

    private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);
    
    private final Environment environment;
    private final ResourceLoader resourceLoader;

    public AppConfig(Environment environment, ResourceLoader resourceLoader) {
        this.environment = environment;
        this.resourceLoader = resourceLoader;
    }

    /**
     * BeanFactoryPostProcessor实现，在容器初始化阶段修改Bean定义
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        logger.info("=== BeanFactoryPostProcessor执行 ===");
        logger.info("活动配置文件: {}", String.join(",", environment.getActiveProfiles()));
        logger.info("应用名称: {}", environment.getProperty("app.name", "未配置"));
        
        // 演示Environment抽象的使用
        String dbUrl = environment.getProperty("spring.datasource.url");
        logger.info("数据库URL: {}", dbUrl);
    }

    /**
     * 自定义BeanPostProcessor，用于记录Bean初始化信息
     */
    @Bean
    public BeanPostProcessor loggingBeanPostProcessor() {
        return new LoggingBeanPostProcessor();
    }

    /**
     * JSR-303验证器
     */
    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    /**
     * 演示Bean生命周期回调
     */
    @PostConstruct
    public void init() {
        logger.info("=== AppConfig初始化完成 ===");
        
        // 演示Resource加载
        Resource resource = resourceLoader.getResource("classpath:application.properties");
        logger.info("配置文件是否存在: {}", resource.exists());
    }

    @PreDestroy
    public void destroy() {
        logger.info("=== AppConfig销毁 ===");
    }
}
